[入門]API Gatewayを利用してS3バケットのオブジェクトを一覧表示させてみた(Lambda統合)
2024.09.30
こんにちは。中村です。
はじめに
API GatewayでLambda統合する構成は、柔軟性があって使いやすくありませんか?
私が初めて利用した時には、感動した思い出があります。
今回は、下記記事でS3からのレスポンスがxml形式であったことに対して、Lambdaプロキシ統合を利用することで解決してみます。
やってみる
テンプレートを作成してみる
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
AppName:
Description: Application Name.
Type: String
Default: api-gateway-s3-list-lambda
Resources:
# ==========
# S3
# ==========
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
BucketName: !Sub "api-gateway-s3-${AWS::AccountId}"
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerEnforced
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
# ==========
# Lambda
# ==========
LambdaExecutionRoleList:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: !Sub ${AppName}-listPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- s3:ListBucket
Resource: !Sub "arn:aws:s3:::${S3Bucket}"
Path: /
RoleName: !Sub ${AppName}-LambdaExecutionRoleList
LambdaFunctionForList:
Type: AWS::Lambda::Function
Properties:
Code:
ZipFile: |
import boto3
import json
import os
import time
S3_BUCKET_NAME = os.environ["S3_BUCKET_NAME"]
s3_client = boto3.client("s3")
def lambda_handler(event, context):
params = {'Bucket': S3_BUCKET_NAME}
objects = []
response = s3_client.list_objects_v2(**params)
for obj in response.get('Contents', []):
objects.append({
'Key': obj['Key'],
'Size': obj['Size']
})
body_str = json.dumps(objects)
return {
'statusCode': 200,
'body': body_str,
'headers': {
'Content-Type': "application/json",
'Content-Length': str(len(body_str)),
'Timestamp': time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime())
}
}
Environment:
Variables:
S3_BUCKET_NAME: !Ref S3Bucket
FunctionName: !Sub ${AppName}-lmd-s3List
Handler: index.lambda_handler
MemorySize: 128
Role: !GetAtt LambdaExecutionRoleList.Arn
Runtime: python3.12
Timeout: 10
# ==========
# API Gateway
# ==========
ApiGatewayRestApi:
Type: AWS::ApiGateway::RestApi
Properties:
BinaryMediaTypes:
- 'image/*'
EndpointConfiguration:
Types:
- REGIONAL
Name: !Ref AppName
ApiGatewayMethodRootList:
Type: AWS::ApiGateway::Method
Properties:
AuthorizationType: AWS_IAM
HttpMethod: GET
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST
Uri: !Sub
- arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaArn}/invocations
- LambdaArn: !GetAtt LambdaFunctionForList.Arn
MethodResponses:
- StatusCode: 200
ResourceId: !GetAtt ApiGatewayRestApi.RootResourceId
RestApiId: !Ref ApiGatewayRestApi
LambdaPermissionRootGET:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref LambdaFunctionForList
Principal: apigateway.amazonaws.com
SourceArn: !Sub
- arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${MyApi}/*/GET/
- MyApi: !Ref ApiGatewayRestApi
やってみた
- 上記テンプレートを利用してCloudFormationでリソースを作成する
- 作成されたS3バケットに任意のファイルをアップロードする
- API Gatewayサービスから、作成したAPIの「テスト」タブを表示させる
- 「テスト」を押下する
- レスポンスを確認する
- Lambdaで整形したjson形式で、2でアップロードしたファイル名が出力されていることが確認できます。
削除する際の留意点
Lambdaを実行した際にCloudWatch logsのロググループにLambdaのログが出力されています。
リソースを削除する際は、ロググループの削除も必要に応じて実施ください。
さいごに
今回は、Lambdaプロキシ統合を利用したAPI Gatewayを構築してみました。
Lambdaを利用することによって細かい処理にも対応できるようになるのが嬉しいですね。
本記事で紹介しているコードはサンプルであり、パフォーマンスや例外処理など一切考慮していないため、本番運用する際は十分にご検討ください。